<template>
  <div class="pdf-container">
    <div class="pdf-view">
      <div ref="pdfWrapperRef" class="pdf-wrapper" v-for="item in pdfState.pageCount" :key="item">
        <canvas :key="item" ref="canvasRefs"></canvas>
        <div v-if="pdfState.pageRendered" class="page">
          {{ item }} / {{ pdfState.pageCount }}
        </div>
        <img v-if="signImg" v-draggable :src="signImg" alt="" style="position: absolute;right: 10px;bottom: 10px;width: 63px;height: 63px">
      </div>
    </div>
    <!-- <div>
      <span
        >Page: <span id="page_num">{{ pdfState.pageNum }}</span> /
        <span id="page_count">{{ pdfState.pageCount }}</span></span
      >
      <button @click="handleLoadPdf">load</button>
      <button ref="preRef">上一页</button>
      <button ref="nextRef">下一页</button>
    </div> -->
  </div>
</template>

<script>
import { mapState } from 'vuex'
// import { GlobalWorkerOptions } from 'pdfjs-dist'
// import * as pdfWorker from 'pdfjs-dist/build/pdf.worker.min.js'
let pdfjsLib = null

function loadPdf () {
  return new Promise((resolve) => {
    if (pdfjsLib) return resolve(pdfjsLib)
    import('pdfjs-dist/build/pdf').then((pdf) => {
      pdfjsLib = pdf
      pdf.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.js'
      resolve(pdfjsLib)
    })
  })
}

const url = 'http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf'
// "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf";
// 'http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf'

// 此处为正确写法---原来我的参数用的响应式写法，就会报错Cannot read from private field
let pdfDoc = '' // 文档内容---必须使用非响应式存储
export default {
  data () {
    return {
      preRef: null,
      nextRef: null,
      pdfState: {
        pageNum: 1,
        pageRendering: false,
        pageNumPending: null,
        scale: 1,
        pageCount: 1,
        pageRendered: false
      }
    }
  },
  directives: {
    draggable: {
      bind: function (el, binding, vnode) {
        let startX, startY, initialLeft, initialTop, dragElement

        const touchStart = (e) => {
          dragElement = e.target

          // 确保是在移动端元素上触发
          if (e.targetTouches.length === 1) {
            // 记录初始位置
            startX = e.targetTouches[0].clientX
            startY = e.targetTouches[0].clientY
            initialLeft = dragElement.offsetLeft
            initialTop = dragElement.offsetTop

            // 添加移动和结束监听器
            el.addEventListener('touchmove', touchMove)
            el.addEventListener('touchend', touchEnd)
          }
        }

        const touchMove = (e) => {
          e.preventDefault()

          const deltaX = e.targetTouches[0].clientX - startX
          const deltaY = e.targetTouches[0].clientY - startY

          // 新的位置
          let newLeft = initialLeft + deltaX
          let newTop = initialTop + deltaY

          // 父元素的边界
          const parentRect = el.parentNode.getBoundingClientRect()

          // 考虑滚动条的滚动
          const scrollLeft = el.parentNode.scrollLeft
          const scrollTop = el.parentNode.scrollTop

          // 边界处理
          newLeft = Math.max(scrollLeft, Math.min(newLeft, scrollLeft + parentRect.width - dragElement.offsetWidth))
          newTop = Math.max(scrollTop, Math.min(newTop, scrollTop + parentRect.height - dragElement.offsetHeight))

          // 应用新位置
          dragElement.style.left = `${newLeft}px`
          dragElement.style.top = `${newTop}px`
        }

        const touchEnd = () => {
          el.removeEventListener('touchmove', touchMove)
          el.removeEventListener('touchend', touchEnd)
        }

        // 监听初始触摸事件
        el.addEventListener('touchstart', touchStart)
      },
      unbind: function (el) {
        // 清理事件监听器
        el.removeEventListener('touchstart', this.touchStart)
        el.removeEventListener('touchmove', this.touchMove)
        el.removeEventListener('touchend', this.touchEnd)
      }
    }
  },
  computed: {
    ...mapState(['signImg'])
  },
  mounted () {
    loadPdf().then((pdf) => {
      // console.log('pdf==', pdf, pdfjsLib, this.signImg)
      this.initPdf()
    })
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    initPdf () {
      const loadingTask = pdfjsLib.getDocument(url)
      // console.log('initPdf ~ loadingTask:', loadingTask)
      loadingTask.promise.then((pdfDoc_) => {
        // console.log(
        //   'file: Pdf.vue:111 ~ pdfjsLib.getDocument ~ pdfDoc_:',
        //   pdfDoc_
        // )
        pdfDoc = pdfDoc_
        this.pdfState.pageCount = pdfDoc.numPages
        // Initial/first page rendering
        this.renderPage(this.pdfState.pageNum)
      })
    },
    async handleResize () {
      await pdfDoc?.destroy()
      this.pdfState = {
        pageNum: 1,
        pageRendering: false,
        pageNumPending: null,
        scale: 1,
        pageCount: 1,
        pageRendered: false
      }
      this.initPdf()
    },
    // createSignImg (x, y, width = 63, height = 63) {
    //   return new Promise((resolve) => {
    //     const image = new Image()
    //     image.src = this.signImg
    //     image.width = width
    //     image.height = height
    //     image.style.position = 'absolute'
    //     image.style.left = x + 'px'
    //     image.style.top = y + 'px'
    //     image.onload = () => {
    //       resolve(image)
    //     }
    //   })
    // },
    // appendImage (parent, img) {
    //   parent.appendChild(img)
    // },
    // addDrag (el, container) {
    //   let isDraging = false
    //   let startX = 0
    //   let startY = 0

    //   el.addEventListener('touchstart', (e) => {
    //     isDraging = true
    //     const touch = e.touches[0]
    //     startX = touch.clientX
    //     startY = touch.clientY
    //   })

    //   el.addEventListener('touchmove', (e) => {
    //     // 防止屏幕滚动
    //     e.preventDefault()
    //     if (isDraging) {
    //       const touch = e.touches[0]
    //       console.log('el.addEventListener ~ touch:', touch)
    //       const deltaX = touch.clientX - startX
    //       const deltaY = touch.clientY - startY

    //       // 计算图片新的位置
    //       let newLeft = el.offsetLeft + deltaX
    //       let newTop = el.offsetTop + deltaY

    //       // 获取容器的尺寸
    //       const containerRect = container.getBoundingClientRect()
    //       console.log('el.addEventListener ~ containerRect:', containerRect)
    //       const scrollLeft = container.scrollLeft
    //       const scrollTop = container.scrollTop

    //       // 边界检查
    //       newLeft = Math.max(scrollLeft, newLeft) // 左边界
    //       newLeft = Math.min(scrollLeft + containerRect.width - el.width, newLeft) // 右边界
    //       newTop = Math.max(scrollTop, newTop) // 上边界
    //       newTop = Math.min(scrollTop + containerRect.height - el.height, newTop) // 下边界

    //       // 图片尺寸
    //       const imageRect = el.getBoundingClientRect()
    //       console.log('el.addEventListener ~ imageRect:', imageRect)

    //       // 边界检查
    //       newLeft = Math.max(containerRect.left, newLeft) // 左边界
    //       newLeft = Math.min(containerRect.right - imageRect.width, newLeft) // 右边界
    //       newTop = Math.max(containerRect.top, newTop) // 上边界
    //       newTop = Math.min(containerRect.bottom - imageRect.height, newTop) // 下边界

    //       // 应用新位置
    //       el.style.left = `${newLeft}px`
    //       el.style.top = `${newTop}px`

    //       startX = touch.clientX
    //       startY = touch.clientY
    //     }
    //   })

    //   el.addEventListener('touchend', () => {
    //     isDraging = false
    //   })
    // },
    renderPage (num) {
      this.pdfState.pageRendering = true
      // Using promise to fetch the page
      pdfDoc.getPage(num).then((page) => {
        // console.log('page==', page)
        const viewport = page.getViewport({ scale: this.pdfState.scale })
        // 40 padding
        const widthScale = document.body.clientWidth / viewport.width
        const heightScale = document.body.clientHeight / viewport.height
        const scaledViewport = page.getViewport({ scale: widthScale })
        const ctx = this.$refs.canvasRefs[num - 1].getContext('2d')
        const dpr = window.devicePixelRatio || 1
        // let bsr =
        //   ctx.webkitBackingStorePixelRatio ||
        //   ctx.mozBackingStorePixelRatio ||
        //   ctx.msBackingStorePixelRatio ||
        //   ctx.oBackingStorePixelRatio ||
        //   ctx.backingStorePixelRatio ||
        //   1;
        // let ratio = dpr / bsr;
        this.$refs.canvasRefs[num - 1].width = Math.floor(
          viewport.width * widthScale * dpr - 40
        )
        this.$refs.canvasRefs[num - 1].height = Math.floor(
          viewport.height * heightScale * dpr - 40
        )
        const cW = Math.floor(viewport.width * widthScale - 40)
        const cH = Math.floor(viewport.height * heightScale - 40)
        this.$refs.canvasRefs[num - 1].style.width = cW + 'px'
        this.$refs.canvasRefs[num - 1].style.height = cH + 'px'
        // this.createSignImg(cW - 80, cH - 80).then(res => {
        //   this.appendImage(this.$refs.pdfWrapperRef[num - 1], res)
        //   this.addDrag(res, this.$refs.pdfWrapperRef[num - 1])
        // })

        const transform = dpr !== 1 ? [dpr, 0, 0, dpr, 0, 0] : null
        // canvasRefs.value[num - 1].width = viewport.width * ratio;
        // canvasRefs.value[num - 1].height = viewport.height * ratio;
        // ctx.setTransform(ratio, 0, 0, ratio, 0, 0);

        // console.log('viewport=', viewport, this.$refs.canvasRefs[num - 1])

        // Render PDF page into canvas context
        const renderContext = {
          canvasContext: ctx,
          transform: transform,
          viewport: scaledViewport,
          pageColors: {
            color: '#f00'
          }
        }
        const renderTask = page.render(renderContext)

        // Wait for rendering to finish
        renderTask.promise.then(() => {
          this.pdfState.pageRendering = false
          if (this.pdfState.pageNumPending !== null) {
            // New page rendering is pending
            this.renderPage(this.pdfState.pageNumPending)
            this.pdfState.pageNumPending = null
          }
        })
        this.pdfState.pageRendered = this.pdfState.pageCount === num
        if (this.pdfState.pageCount > num) {
          this.renderPage(num + 1)
        }
      })

      // Update page counters
      this.pdfState.pageNum = num
    },
    queueRenderPage (num) {
      if (this.pdfState.pageRendering) {
        this.pdfState.pageNumPending = num
      } else {
        this.renderPage(num)
      }
    },
    onPrevPage () {
      if (this.pdfState.pageNum <= 1) {
        return
      }
      this.pdfState.pageNum--
      this.queueRenderPage(this.pdfState.pageNum)
    },
    onNextPage () {
      if (this.pdfState.pageNum >= pdfDoc.numPages) {
        return
      }
      this.pdfState.pageNum++
      this.queueRenderPage(this.pdfState.pageNum)
    }
  }
}
</script>

<style lang="scss" scoped>
.pdf-container,
.pdf-view {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
}

.pdf-view {
  background-color: #d9e6fb;
  padding: 20px;

  .pdf-wrapper {
    position: relative;
    margin-bottom: 20px;

    &:last-child {
      margin-bottom: 0;
    }

    .page {
      position: absolute;
      bottom: -14px;
      left: 50%;
      transform: translateX(-50%);
      font-size: 12px;
    }
  }
}
</style>
